
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include "Response.h"
#include "Request.h"
#ifdef SERVER
#include "Device.h"
#endif

using namespace boost;

namespace Engine {

CResponse::CResponse(void)
{
}

CResponse::CResponse(string& head, boost::asio::streambuf& data) 
	: CPackage(data)
{
	ParseHead(head);
	PostParse();
}

CResponse::CResponse(string& head, boost::shared_ptr<std::istream> is)
	: CPackage(is)
{
	ParseHead(head);
	PostParse();
}

CResponse::~CResponse(void)
{
}

void CResponse::PostParse()
{
	string auth = GetPropertie(string(PACKAGE_PROP_AUTHENTICATE));
	if(auth.length() > 0) {
		ParseAuthInfo(auth);
	}
}

void CResponse::SetStatus(int s) 
{ 
	mStatus = s;
	switch(mStatus) {
	case RESPONSE_STATUS_OK :
		mStatusDesc = "OK";
		break;
	case RESPONSE_STATUS_BadRequest :
		mStatusDesc = "Bad Request";
		break;
	case RESPONSE_STATUS_Unauthozied :
		mStatusDesc = "Unauthozied";
		break;
	case RESPONSE_STATUS_Forbidden :
		mStatusDesc = "Forbidden";
		break;
	case RESPONSE_STATUS_FileNotFound :
		mStatusDesc = "File Not Found";
		break;
	case RESPONSE_STATUS_SessionNotFound :
		mStatusDesc = "Session Not Found";
		break;
	}
}

void CResponse::ParseHead(string &line)
{
	string::size_type pos = line.find(PROTOCOL_TAG);
	if(pos != 0) throw CPackageParseException() << parse_error("No response header : " + line);

	std::vector<string> s;
	algorithm::split(s, line, is_any_of(" "));
	if(s.size() < 2) throw CPackageParseException() << parse_error("Invalid response header : " + line);

	try
	{
		mStatus = boost::lexical_cast<int>(s[1]);
	}
	catch(boost::bad_lexical_cast&)
	{
		throw CPackageParseException() << parse_error("Invalid response header : " + line);
	}

	if(s.size() > 2) mStatusDesc = s[2];
}

void CResponse::ParseAuthInfo(string& value)
{
	string s1;
	string s2;
	int pos;
	int offset = 0;

	// type
	pos = value.find(' ');
	if(pos < 0) throw CPackageParseException() << parse_error("Invalid athenticate line : " + value);
	s2 = value.substr(offset, pos-offset);
	boost::algorithm::trim(s2);
	mAuthInfo[string(AUTH_INFO_TYPE)] = s2;
	offset = pos + 1;

	//others
	while(offset > 0 && offset < value.length()) {
		pos = value.find('=', offset);
		if(pos < 0) break;
		s1 = value.substr(offset, pos-offset);
		boost::algorithm::trim(s1);
		offset = pos + 1;

		if(value[offset] == '"') {
			offset++;
			pos = value.find('"', offset);
			if(pos < 0) throw CPackageParseException() << parse_error("Invalue authorization format follow : " + s1);
			s2 = value.substr(offset, pos-offset);
			boost::algorithm::trim(s2);
			pos = value.find(',', pos);
		}
		else {
			pos = value.find(',', offset);
			if(pos > 0) s2 = value.substr(offset, pos-offset);
			else s2 = value.substr(offset);
			boost::algorithm::trim(s2);
		}

		mAuthInfo[s1] = s2;
		
		if(pos < 0) break;
		offset = pos + 1;
	}

}

void CResponse::GetData(ostream& os)
{
	os << PROTOCOL_TAG << ' ' << boost::lexical_cast<string>(mStatus);
	if(mStatusDesc.length() > 0) os << ' ' << mStatusDesc; 
	os << "\r\n";
	CPackage::GetData(os);
}

bool CResponse::MatchRequest(boost::shared_ptr<CRequest> r)
{
	string magic = GetPropertie(string(PACKAGE_PROP_MAGIC));
	string magic_r = r->GetPropertie(string(PACKAGE_PROP_MAGIC));

	return magic.length()> 0 && magic_r.length() > 0 && magic == magic_r;
}

}
